/**
 * 
 */
package edu.gtcfla.km.admin.appmodules.web;

import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONArray;
import net.sf.json.JsonConfig;

import org.apache.shiro.authz.annotation.RequiresUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.vsg.biz.BusinessEntityFactory;
import org.vsg.common.i18n.I18nMessageService;
import org.vsg.common.web.json.ItemsResult;
import org.vsg.common.web.json.ListResult;
import org.vsg.common.web.json.SelectItem;
import org.vsg.common.web.json.SubmitResult;
import org.vsg.common.web.json.processor.JsDateViewJsonValueProcessor;
import org.vsg.search.api.criterion.MapPaginaitionCriteria;
import org.vsg.search.api.criterion.PaginationCriteria;
import org.vsg.search.api.criterion.SearchCriteriaCls;
import org.vsg.security.annotation.RegisterRequestPermissionStrategy;

import com.fasterxml.jackson.databind.ObjectMapper;

import edu.gtcfla.km.admin.appmodules.service.FunctionManagerService;
import edu.gtcfla.km.admin.appmodules.service.MenuManagerService;
import edu.gtcfla.km.admin.appmodules.service.ModuleManagerService;
import edu.gtcfla.km.admin.appmodules.service.RoleService;
import edu.gtcfla.km.admin.appmodules.vo.HierarchyMenuResourcePermissionVO;
import edu.gtcfla.km.admin.appmodules.vo.ModuleFunctionPermissionVO;
import edu.gtcfla.km.admin.appmodules.vo.ModulePermissionVO;
import edu.gtcfla.km.admin.appmodules.vo.RoleFormVO;
import edu.gtcfla.km.admin.appmodules.vo.RoleListedVO;
import edu.gtcfla.km.core.ApplicationConstant;

/**
 * @author Bill Vison
 * 
 */
@Controller
@Lazy
@RequestMapping(ApplicationConstant.DATA_RERESOURCE)
public class RoleController {

	private final static Logger logger = LoggerFactory
			.getLogger(ModuleController.class);

	private final String modulePath = "/role";

	private String modulePrefix = ApplicationConstant.DATA_RERESOURCE
			+ modulePath;

	@Autowired(required = false)
	private I18nMessageService i18nMessageService;

	@Autowired(required = false)
	private RoleService roleService;

	@Autowired(required = false)
	private ModuleManagerService moduleManagerService;

	@Autowired(required = false)
	private FunctionManagerService functionManagerService;

	@Autowired(required = false)
	private MenuManagerService menuManagerService;

	private ObjectMapper objectMapper = new ObjectMapper();	
	
	@Autowired
	private BusinessEntityFactory entityFactory;


	@SearchCriteriaCls(criteriaClass = MapPaginaitionCriteria.class)
	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/paging.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/paging.json")
	public @ResponseBody
	ListResult accessPageRoles(PaginationCriteria criteria,
			HttpServletRequest request) throws Exception {

		Page page = roleService.pageRoles(criteria);

		ListResult lr = new ListResult();
		lr.setRows(page.getContent());
		lr.setResults((int) page.getTotalElements());

		return lr;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/allselect.json", skipCheck = true)
	@RequestMapping(value = modulePath	+"/allrolesforselected.json")
	public ModelAndView accessAllrolesforselected() throws Exception {

		Set<RoleListedVO> roles = roleService.findAllRolesForSelected();

		JsonConfig jcfg = new JsonConfig();
		jcfg.registerJsonValueProcessor(java.util.Date.class,
				new JsDateViewJsonValueProcessor());
		JSONArray jsonObject = JSONArray.fromObject(roles, jcfg);

		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name

		return mav;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/function/list.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/function/list.json")
	public  @ResponseBody ListResult accessListAuthModuleFunctions(String roleId,
			String modResId) throws Exception {

		Set<ModuleFunctionPermissionVO> funPerms = functionManagerService
				.listPermissionFunsByRoleId(roleId, modResId);

		ListResult listResult = new ListResult();
		listResult.setRows(funPerms);
		listResult.setResults(funPerms.size());


		return listResult;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/module/list.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/module/list.json")
	public @ResponseBody ListResult accessListAuthModules(String roleId) throws Exception {

		Set<ModulePermissionVO> perms = moduleManagerService
				.listPermissionModulesByRoleId(roleId);

		ListResult listResult = new ListResult();
		listResult.setRows(perms);
		listResult.setResults(perms.size());


		return listResult;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/menu/list.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/menu/list.json")
	public  @ResponseBody  Set<HierarchyMenuResourcePermissionVO> accessListAuthMenus(String roleId) throws Exception {

		Set<HierarchyMenuResourcePermissionVO> menus = menuManagerService.buildHierachyMenuPermissionByRoleId(roleId);

		return menus;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/menu/update.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/menu/update.json")
	public @ResponseBody SubmitResult accessUpdateAuthMenus(String roleId , @RequestBody List<Map<String,Object>> receiveValues)
			throws Exception {

		Set<HierarchyMenuResourcePermissionVO> resPerms = new LinkedHashSet<HierarchyMenuResourcePermissionVO>();
		
		for (Map<String,Object> item : receiveValues) {

			  HierarchyMenuResourcePermissionVO permsVO = new  HierarchyMenuResourcePermissionVO(); 
			  permsVO.setId( (String)item.get("id"));
			  permsVO.setAcl( (String) item.get("acl")); 
			  permsVO.setText( (String) item.get("text"));
			  permsVO.setMenuLevel((Integer) item.get("menuLevel"));
			  
			  resPerms.add(permsVO);
		}
		
		// --- remove user id ---

		SubmitResult result = new SubmitResult();
		try {

			menuManagerService.authMenusWithUnderRes(roleId, resPerms);

			result.setSuccess(true);
			String msg = i18nMessageService.getMessage(
					"module-admin.menu.auth.updated.success", null);
			result.setMsg(msg);

		} catch (Exception se) {
			// TODO Auto-generated catch block
			se.printStackTrace();
			result.setSuccess(false);
			String msg = i18nMessageService.getMessage(
					"module-admin.menu.auth.updated.error", null);
			result.setMsg(msg);
		}



		return result;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/module/update.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/module/update.json")
	public @ResponseBody SubmitResult accessUpdateAuthModules(String roleId , 
				@RequestBody List<Map<String,Object>> receiveValues)
			throws Exception {
		
		Set<ModulePermissionVO> modulesPermChanged = new LinkedHashSet<ModulePermissionVO>();
		
		for (Map<String,Object> map : receiveValues) {
			
			ModulePermissionVO mpv = new ModulePermissionVO();
			mpv.setId( (String)map.get("id") );
			mpv.setName((String) map.get("name") );
			mpv.setCode( (String) map.get("code"));
			mpv.setAcl( (String) map.get("acl" ) );
			mpv.setVersion( (String) map.get("version") );
			mpv.setReleaseDate( (String)map.get("releaseDate")  );
			
			modulesPermChanged.add( mpv);
		}

		// --- map to json object data ---
		SubmitResult result = new SubmitResult();		

		// --- remove user id ---
		try {
			if(!modulesPermChanged.isEmpty()) {
				moduleManagerService.authModuleWithUnderRes(roleId, modulesPermChanged);
			}

			result.setSuccess(true);
			String msg = i18nMessageService.getMessage(
					"module-admin.module.auth.updated.success", null);
			result.setMsg(msg);

		} catch (Exception se) {
			// TODO Auto-generated catch block
			se.printStackTrace();
			result.setSuccess(false);
			String msg = i18nMessageService.getMessage(
					"module-admin.module.auth.updated.error", null);
			result.setMsg(msg);
		}		

		return result;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/function/update.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/function/update.json")
	public @ResponseBody SubmitResult accessUpdateAuthModuleFunctions(String roleId , String modResId , @RequestBody List<Map<String,Object>> receiveValues) throws Exception {


		// --- map to json object data ---
		SubmitResult result = new SubmitResult();

		// --- remove user id ---

		Set<ModuleFunctionPermissionVO> mods = new LinkedHashSet<ModuleFunctionPermissionVO>();

		for (Map<String,Object> map : receiveValues) {
			
			ModuleFunctionPermissionVO funPerm = new ModuleFunctionPermissionVO();
			funPerm.setId( (String)map.get("id") );
			funPerm.setName((String)map.get("name") );
			funPerm.setAcl( (String)map.get("acl") );
			
			mods.add( funPerm );	
		}
		
		try {


			functionManagerService.authFunsWithUnderRes(roleId, modResId, mods);

			result.setSuccess(true);
			String msg = i18nMessageService.getMessage(
					"module-admin.function.auth.updated.success", null);
			result.setMsg(msg);

		} catch (Exception se) {
			// TODO Auto-generated catch block
			se.printStackTrace();
			result.setSuccess(false);
			String msg = i18nMessageService.getMessage(
					"module-admin.function.auth.updated.error", null);
			result.setMsg(msg);
		}

		return result;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/submit_deleteall.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/submit_deleteall.json")
	@ResponseBody
	public SubmitResult accessDeleteRolessDirectly(@RequestBody List<String> receiveValues)
			throws Exception {

		// --- map to json object data ---
		SubmitResult result = new SubmitResult();

		// --- remove user id ---
		try {
			if ( receiveValues != null && !receiveValues.isEmpty() ) {
				
				roleService.deleteDirectlyByRoleIds( receiveValues.toArray(new String[0]) );

			}	


			result.setSuccess(true);
			String msg = i18nMessageService.getMessage(
					"module-admin.role.delete.success", null);
			result.setMsg(msg);

		} catch (Exception se) {
			// TODO Auto-generated catch block
			se.printStackTrace();
			result.setSuccess(false);
			String msg = i18nMessageService.getMessage(
					"module-admin.role.delete.success", null);
			result.setMsg(msg);
		}

		return result;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/submit_adding.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/submit_adding.json")
	@ResponseBody
	public SubmitResult accessAddRole(RoleFormVO role) throws Exception {

		// --- map to json object data ---
		SubmitResult result = new SubmitResult();

		try {
			roleService.addRole(role);
			result.setSuccess(true);
			String msg = i18nMessageService.getMessage(
					"module-admin.role.add.success", null);
			result.setMsg(msg);

		} catch (Exception e) {

			e.printStackTrace();
			result.setSuccess(false);
			String msg = i18nMessageService.getMessage(
					"module-admin.role.add.error", null);
			result.setMsg(msg);

		}

		return result;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/load.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/load.json")
	@ResponseBody
	public SubmitResult accessLoadRole(String roleId) throws Exception {

		SubmitResult submitResult = new SubmitResult();

		RoleFormVO roleVo = roleService.loadRole(roleId);

		submitResult.setSuccess(true);
		submitResult.setData(roleVo);

		return submitResult;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/submit_updating.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/submit_updating.json")
	@ResponseBody
	public SubmitResult accessUpdateRole(RoleFormVO role) throws Exception {

		// --- map to json object data ---
		SubmitResult result = new SubmitResult();

		try {
			this.roleService.updateRole(role);
			result.setSuccess(true);
			String msg = i18nMessageService.getMessage(
					"module-admin.user.update.success", null);
			result.setMsg(msg);

		} catch (Exception e) {

			e.printStackTrace();
			result.setSuccess(false);
			String msg = i18nMessageService.getMessage(
					"module-admin.user.update.error", null);
			result.setMsg(msg);

		}

		return result;
	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "select_availablesystemroles.json", skipCheck = true)
	@RequestMapping(value = modulePath	+ "/select_availablesystemroles.json")
	public ModelAndView accessSelectAvailableSystemRoles() throws Exception {

		// --- map to json object data ---
		Set<Map<String, String>> systemRoles = new LinkedHashSet<Map<String, String>>();

		try {

			Map<String, String> sRole = new LinkedHashMap<String, String>();
			sRole.put("id", "superadmin");
			sRole.put("name", "superadmin");
			systemRoles.add(sRole);

			sRole = new LinkedHashMap<String, String>();
			sRole.put("id", "business");
			sRole.put("name", "business");
			systemRoles.add(sRole);

		} catch (Exception e) {

			e.printStackTrace();

		}

		JsonConfig jcfg = new JsonConfig();
		jcfg.registerJsonValueProcessor(java.util.Date.class,
				new JsDateViewJsonValueProcessor());
		JSONArray jsonObject = JSONArray.fromObject(systemRoles, jcfg);

		// --- reflesh ----

		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name

		return mav;
	}
	
	
	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/all_available", skipCheck = true)
	@RequestMapping(value = modulePath + "/all_available.json")
	public @ResponseBody ItemsResult accessAllAvailable() throws Exception {

		// --- map to json object data ---
		ItemsResult result = new ItemsResult();

		// --- remove user id ---
		try {

			Set<SelectItem> selItems = roleService.findAvailableRoles();
			result.setRoot( (Set)selItems );

			result.setSuccess(true);

		} catch (Exception se) {

		}

		return result;
	}	
	
	@RequiresUser
	@RegisterRequestPermissionStrategy(value = "/role/systemrole/all_available", skipCheck = true)
	@RequestMapping(value = modulePath + "/systemrole/all_available.json")
	public @ResponseBody ItemsResult accessAllSystemRole() throws Exception {

		// --- map to json object data ---
		ItemsResult result = new ItemsResult();

		// --- remove user id ---
		try {

			Set<SelectItem> selItems = roleService.findAllSystemRoles();
			result.setRoot( (Set)selItems );

			result.setSuccess(true);

		} catch (Exception se) {

		}

		return result;
	}		
	
}
